home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / network / admin / dig-2.0 / dig-2 / dig.2.0 / res_query.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-09-04  |  6.8 KB  |  270 lines

  1.  
  2. /*
  3.  * Copyright (c) 1988 Regents of the University of California.
  4.  * All rights reserved.
  5.  *
  6.  * Redistribution and use in source and binary forms are permitted
  7.  * provided that this notice is preserved and that due credit is given
  8.  * to the University of California at Berkeley. The name of the University
  9.  * may not be used to endorse or promote products derived from this
  10.  * software without specific prior written permission. This software
  11.  * is provided ``as is'' without express or implied warranty.
  12.  */
  13.  
  14. /*
  15. ** Modified for and distributed with 'dig' version 2.0 from
  16. ** University of Southern California Information Sciences Institute
  17. ** (USC-ISI). 9/1/90
  18. */
  19.  
  20.  
  21. #if defined(LIBC_SCCS) && !defined(lint)
  22. static char sccsid[] = "@(#)res_query.c    5.4 (Berkeley) 4/21/88";
  23. #endif /* LIBC_SCCS and not lint */
  24.  
  25.  
  26. #include "hfiles.h"
  27.  
  28. #include PARAMH
  29. #include <sys/socket.h>
  30. #include <netinet/in.h>
  31. #include <ctype.h>
  32. #include NETDBH
  33. #include <stdio.h>
  34. #include <errno.h>
  35. #include <strings.h>
  36. #include <arpa/inet.h>
  37. #include NAMESERH
  38. #ifndef T_TXT
  39. #define T_TXT 16
  40. #endif T_TXT
  41. #include RESOLVH
  42.  
  43. #if PACKETSZ > 1024
  44. #define MAXPACKET    PACKETSZ
  45. #else
  46. #define MAXPACKET    1024
  47. #endif
  48.  
  49. #ifndef RES_DEBUG2
  50. #define RES_DEBUG2      0x80000000
  51. #endif
  52.  
  53. extern int errno;
  54. int h_errno;
  55.  
  56. /*
  57.  * Formulate a normal query, send, and await answer.
  58.  * Returned answer is placed in supplied buffer "answer".
  59.  * Perform preliminary check of answer, returning success only
  60.  * if no error is indicated and the answer count is nonzero.
  61.  * Return the size of the response on success, -1 on error.
  62.  * Error number is left in h_errno.
  63.  * Caller must parse answer and determine whether it answers the question.
  64.  */
  65. res_query(name, class, type, answer, anslen)
  66.     char *name;        /* domain name */
  67.     int class, type;    /* class and type of query */
  68.     u_char *answer;        /* buffer to put answer */
  69.     int anslen;        /* size of answer buffer */
  70. {
  71.     char buf[MAXPACKET];
  72.     HEADER *hp;
  73.     int n;
  74.  
  75.     if ((_res.options & RES_INIT) == 0 && res_init() == -1)
  76.         return (-1);
  77. #ifdef DEBUG
  78.     if (_res.options & RES_DEBUG2)
  79.         printf(";; res_query(%s, %d, %d)\n", name, class, type);
  80. #endif
  81.     n = res_mkquery(QUERY, name, class, type, (char *)NULL, 0, NULL,
  82.         buf, sizeof(buf));
  83.  
  84.     if (n <= 0) {
  85. #ifdef DEBUG
  86.         if (_res.options & RES_DEBUG)
  87.             printf(";; res_query: mkquery failed\n");
  88. #endif
  89.         h_errno = NO_RECOVERY;
  90.         return (n);
  91.     }
  92.     n = res_send(buf, n, answer, anslen);
  93.     if (n < 0) {
  94. #ifdef DEBUG
  95.         if (_res.options & RES_DEBUG)
  96.             printf(";; res_query: send error\n");
  97. #endif
  98.         h_errno = TRY_AGAIN;
  99.         return(n);
  100.     }
  101.  
  102.     hp = (HEADER *) answer;
  103.     if (hp->rcode != NOERROR || ntohs(hp->ancount) == 0) {
  104. #ifdef DEBUG
  105.         if (_res.options & RES_DEBUG2)
  106.             printf(";; rcode = %d, ancount=%d\n", hp->rcode,
  107.                 ntohs(hp->ancount));
  108. #endif
  109.         switch (hp->rcode) {
  110.             case NXDOMAIN:
  111.                 h_errno = HOST_NOT_FOUND;
  112.                 break;
  113.             case SERVFAIL:
  114.                 h_errno = TRY_AGAIN;
  115.                 break;
  116.             case NOERROR:
  117.                 h_errno = NO_DATA;
  118.                 break;
  119.             case FORMERR:
  120.             case NOTIMP:
  121.             case REFUSED:
  122.             default:
  123.                 h_errno = NO_RECOVERY;
  124.                 break;
  125.         }
  126.         return (-1);
  127.     }
  128.     return(n);
  129. }
  130.  
  131. /*
  132.  * Formulate a normal query, send, and retrieve answer in supplied buffer.
  133.  * Return the size of the response on success, -1 on error.
  134.  * If enabled, implement search rules until answer or unrecoverable failure
  135.  * is detected.  Error number is left in h_errno.
  136.  * Only useful for queries in the same name hierarchy as the local host
  137.  * (not, for example, for host address-to-name lookups in domain in-addr.arpa).
  138.  */
  139. res_search(name, class, type, answer, anslen)
  140.     char *name;        /* domain name */
  141.     int class, type;    /* class and type of query */
  142.     u_char *answer;        /* buffer to put answer */
  143.     int anslen;        /* size of answer */
  144. {
  145.     register char *cp, **domain;
  146.     int n, ret, got_nodata = 0;
  147.     char *hostalias();
  148.  
  149.     if ((_res.options & RES_INIT) == 0 && res_init() == -1)
  150.         return (-1);
  151.  
  152.     errno = 0;
  153.     h_errno = HOST_NOT_FOUND;        /* default, if we never query */
  154.     for (cp = name, n = 0; *cp; cp++)
  155.         if (*cp == '.')
  156.             n++;
  157.     if (n == 0 && (cp = hostalias(name)))
  158.         return (res_query(cp, class, type, answer, anslen));
  159.  
  160.     if ((n == 0 || *--cp != '.') && (_res.options & RES_DEFNAMES))
  161.         for (domain = _res.dnsrch; *domain; domain++) {
  162.         ret = res_querydomain(name, *domain, class, type,
  163.             answer, anslen);
  164.         if (ret > 0)
  165.             return (ret);
  166.         /*
  167.          * If no server present, give up.
  168.          * If name isn't found in this domain,
  169.          * keep trying higher domains in the search list
  170.          * (if that's enabled).
  171.          * On a NO_DATA error, keep trying, otherwise
  172.          * a wildcard entry of another type could keep us
  173.          * from finding this entry higher in the domain.
  174.          * If we get some other error (non-authoritative negative
  175.          * answer or server failure), then stop searching up,
  176.          * but try the input name below in case it's fully-qualified.
  177.          */
  178.         if (errno == ECONNREFUSED) {
  179.             h_errno = TRY_AGAIN;
  180.             return (-1);
  181.         }
  182.         if (h_errno == NO_DATA)
  183.             got_nodata++;
  184.         if ((h_errno != HOST_NOT_FOUND && h_errno != NO_DATA) ||
  185.             (_res.options & RES_DNSRCH) == 0)
  186.             break;
  187.     }
  188.     /*
  189.      * If the search/default failed, try the name as fully-qualified,
  190.      * but only if it contained at least one dot (even trailing).
  191.      */
  192.     if (n)
  193.         return (res_querydomain(name, (char *)NULL, class, type,
  194.             answer, anslen));
  195.     if (got_nodata)
  196.         h_errno = NO_DATA;
  197.     return (-1);
  198. }
  199.  
  200. /*
  201.  * Perform a call on res_query on the concatenation of name and domain,
  202.  * removing a trailing dot from name if domain is NULL.
  203.  */
  204. res_querydomain(name, domain, class, type, answer, anslen)
  205.     char *name, *domain;
  206.     int class, type;    /* class and type of query */
  207.     u_char *answer;        /* buffer to put answer */
  208.     int anslen;        /* size of answer */
  209. {
  210.     char nbuf[2*MAXDNAME+2];
  211.     char *longname = nbuf;
  212.     int n;
  213.  
  214. #ifdef DEBUG
  215.     if (_res.options & RES_DEBUG2)
  216.         printf(";; res_querydomain(%s, %s, %d, %d)\n",
  217.             name, domain, class, type);
  218. #endif
  219.     if (domain == NULL) {
  220.         /*
  221.          * Check for trailing '.';
  222.          * copy without '.' if present.
  223.          */
  224.         n = strlen(name) - 1;
  225.         if (name[n] == '.' && n < sizeof(nbuf) - 1) {
  226.             bcopy(name, nbuf, n);
  227.             nbuf[n] = '\0';
  228.         } else
  229.             longname = name;
  230.     } else
  231.         (void)sprintf(nbuf, "%.*s.%.*s",
  232.             MAXDNAME, name, MAXDNAME, domain);
  233.  
  234.     return (res_query(longname, class, type, answer, anslen));
  235. }
  236.  
  237. char *
  238. hostalias(name)
  239.     register char *name;
  240. {
  241.     register char *C1, *C2;
  242.     FILE *fp;
  243.     char *file, *getenv(), *strcpy(), *strncpy();
  244.     char buf[BUFSIZ];
  245.     static char abuf[MAXDNAME];
  246.  
  247.     file = getenv("HOSTALIASES");
  248.     if (file == NULL || (fp = fopen(file, "r")) == NULL)
  249.         return (NULL);
  250.     buf[sizeof(buf) - 1] = '\0';
  251.     while (fgets(buf, sizeof(buf), fp)) {
  252.         for (C1 = buf; *C1 && !isspace(*C1); ++C1);
  253.         if (!*C1)
  254.             break;
  255.         *C1 = '\0';
  256.         if (!strcasecmp(buf, name)) {
  257.             while (isspace(*++C1));
  258.             if (!*C1)
  259.                 break;
  260.             for (C2 = C1 + 1; *C2 && !isspace(*C2); ++C2);
  261.             abuf[sizeof(abuf) - 1] = *C2 = '\0';
  262.             (void)strncpy(abuf, C1, sizeof(abuf) - 1);
  263.             (void) fclose(fp);
  264.             return (abuf);
  265.         }
  266.     }
  267.     (void) fclose(fp);
  268.     return (NULL);
  269. }
  270.